package com.akoj.anmu.service.impl;

import com.akoj.anmu.common.ResponseCode;
import com.akoj.anmu.constant.UserConstant;
import com.akoj.anmu.exception.BusinessException;
import com.akoj.anmu.service.UserService;
import com.akoj.anmu.service.UserTeamService;
import com.akoj.model.domain.dto.team.*;
import com.akoj.model.domain.entity.User;
import com.akoj.model.domain.entity.UserTeam;
import com.akoj.model.domain.enums.TeamStatus;
import com.akoj.model.domain.vo.LoginUserVO;
import com.akoj.model.domain.vo.TeamVO;
import com.akoj.model.domain.vo.UserVO;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.akoj.model.domain.entity.Team;
import com.akoj.anmu.service.TeamService;
import com.akoj.anmu.mapper.TeamMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author LENOVO
* @description 针对表【team(队伍)】的数据库操作Service实现
* @createDate 2024-10-24 19:30:28
*/
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
    implements TeamService{

    @Resource
    private UserTeamService userTeamService;

    @Resource
    private UserServiceImpl userService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addTeam(TeamAddRequest teamAddRequest, LoginUserVO currentUser) {
        /**
         * 校验信息
         */
        String name = teamAddRequest.getName();
        String description = teamAddRequest.getDescription();
        Integer maxNum = teamAddRequest.getMaxNum();
        Date expireTime = teamAddRequest.getExpireTime();
        Integer status = teamAddRequest.getStatus();
        String password = teamAddRequest.getPassword();
        //队伍人数大于1 且 小于等于 20
        if (maxNum == null || maxNum < 1 || maxNum > 20) {
            throw new BusinessException(ResponseCode.PARAMS_ERROR, "队伍人数有误");
        }
        //队伍标题长度最大为20
        if(StringUtils.isAnyBlank(name) || name.length() > 20){
            throw new BusinessException(ResponseCode.PARAMS_ERROR, "队伍标题有误");
        }
        //队伍描述最大长度512
        if(StringUtils.isAnyBlank(description) || description.length() > 512){
            throw new BusinessException(ResponseCode.PARAMS_ERROR, "队伍描述有误");
        }
        if(status != TeamStatus.PUBLIC.getCode() && status != TeamStatus.PRIVATE.getCode() && status != TeamStatus.SECRET.getCode()){
            throw new BusinessException(ResponseCode.PARAMS_ERROR, "队伍状态有误");
        }
        //队伍状态若为加密，校验密码长度是否只有四位，并且全是数字
        if(status == TeamStatus.SECRET.getCode() && (password.length() != 4 || !StringUtils.isNumeric(password))){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"密码只能是4位并且全是数字");
        }
        //超时时间早于当前时间
        if(expireTime == null || expireTime.before(new Date())){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"过期时间有误");
        }
        //一个用户最多创建5个队伍
        Long userId = currentUser.getId();
        Team team = new Team();
        team.setUserId(userId);
        BeanUtils.copyProperties(teamAddRequest,team);
        QueryWrapper<Team> teamQueryWrapper = new QueryWrapper<>();
        long count = this.count(teamQueryWrapper);
        if(count > 5){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"最多创建5个队伍");
        }
        //插入队伍到队伍表
        boolean Teamsave = this.save(team);
        if(!Teamsave){
            throw new BusinessException(ResponseCode.SERVER_ERROR,"创建队伍失败,系统错误");
        }
        Long teamId = team.getId();
        //插入用户和队伍到用户队伍关系表
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userId);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());

        boolean UserTeamsave = userTeamService.save(userTeam);
        if(!UserTeamsave){
            throw new BusinessException(ResponseCode.SERVER_ERROR,"创建队伍失败,系统错误");
        }
        return teamId;
    }

    @Override
    public List<TeamVO> listAllTeam(TeamQueryRequest teamQueryRequest, LoginUserVO currentUser) {
        //取出查询参数，如果查询参数不为空就进行模糊查询
        QueryWrapper<Team> wrapper = new QueryWrapper<>();
        String searchText = teamQueryRequest.getSearchText();
        String name = teamQueryRequest.getName();
        String description = teamQueryRequest.getDescription();
        if(!StringUtils.isAnyBlank(searchText)){
            wrapper.like("name",searchText).or().like("description",searchText);
        }
        if(!StringUtils.isAnyBlank(name)){
            wrapper.like("name",name);
        }
        if(!StringUtils.isAnyBlank(description)){
            wrapper.like("description",description);
        }
        Page<Team> page = new Page<>(teamQueryRequest.getPageNum(),teamQueryRequest.getPageSize());
        Page<Team> teamPage = this.page(page, wrapper);
        List<Team> teamList = teamPage.getRecords();
        //过滤掉过期时间早于当前时间的队伍
        List<Team> handledTeamList = teamList.stream().filter(team -> (team.getExpireTime().after(new Date()))).collect(Collectors.toList());
        //获取该用户加入和创建的队伍
        Long userId = currentUser.getId();
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("userId",userId);
        List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
        List<Long> userTeamIdList = new ArrayList<>();
        userTeamList.forEach(userTeam -> userTeamIdList.add(userTeam.getTeamId()));
        List<Team> filteredTeamList = new ArrayList<>();
        if(!userTeamIdList.isEmpty()){
            for(UserTeam userTeam : userTeamList){
                filteredTeamList = handledTeamList.stream().filter(team -> {
                    Long teamId = team.getId();
                    return !userTeamIdList.contains(teamId);
                }).collect(Collectors.toList());
            }
            return this.getTeamVoList(filteredTeamList);
        }
        return this.getTeamVoList(handledTeamList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateTeam(TeamUpdateRequest teamUpdateRequest, LoginUserVO currentUser) {
        //判断参数是否为空
        if(teamUpdateRequest == null){
            throw new BusinessException(ResponseCode.PARAMS_ERROR, "参数为空");
        }
        //查询队伍是否存在
        Long teamId = teamUpdateRequest.getId();
        Team team = this.getTeamById(teamId);
        if(team == null){
            throw new BusinessException(ResponseCode.NOT_FOUND, "队伍不存在");
        }
        //只有管理员和队伍的创建者可以修改
        Long LeaderId = currentUser.getId();
        QueryWrapper<Team> teamQueryWrapper = new QueryWrapper<>();
        teamQueryWrapper.eq("userId",LeaderId);
        long count = this.count(teamQueryWrapper);
        //不是队伍的创建者或者也不是管理员
        if(count == 0 && !UserConstant.ADMIN_ROLE.equals(currentUser.getUserRole())){
            throw new BusinessException(ResponseCode.NO_AUTH, "无操作权限");
        }
        //如果队伍状态该为加密，校验密码长度是否只有四位，并且全是数字
        Integer status = teamUpdateRequest.getStatus();
        String password = teamUpdateRequest.getPassword();
        if(TeamStatus.SECRET.getCode() == status){
            if(StringUtils.isAnyBlank(password) || password.length() != 4 || !StringUtils.isNumeric(password)){
                throw new BusinessException(ResponseCode.PARAMS_ERROR,"加密队伍必须设置密码且只能是4位并且全是数字");
            }
        }
        //如果队伍状态改为公开，密码必须为空
        if(TeamStatus.PUBLIC.getCode() == status){
            if(StringUtils.isNotBlank(password)){
                throw new BusinessException(ResponseCode.PARAMS_ERROR, "公开队伍密码必须为空");
            }
        }
        //进行更新操作
        Team newTeam = new Team();
        BeanUtils.copyProperties(teamUpdateRequest,newTeam);
        boolean update = this.updateById(newTeam);
        if(!update){
            throw new BusinessException(ResponseCode.SERVER_ERROR,"更新失败，服务内部出错");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean joinTeam(TeamJoinRequest teamJoinRequest, LoginUserVO currentUser) {
        //判断参数是否为空
        if(teamJoinRequest == null){
            throw new BusinessException(ResponseCode.PARAMS_ERROR, "参数为空");
        }
        Long userId = currentUser.getId();
        Long teamId = teamJoinRequest.getId();
        //一个用户最多加入5个队伍
        QueryWrapper<Team> teamQueryWrapper = new QueryWrapper<>();
        teamQueryWrapper.eq("userId",userId);
        long count = this.count(teamQueryWrapper);
        if(count > 5){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"最多加入5个队伍");
        }
        //队伍必须存在，只能加入未满，过期时间未过期的队伍
        Team team = getTeamById(teamId);
        if(team == null){
            throw new BusinessException(ResponseCode.NOT_FOUND,"队伍不存在");
        }
        Integer maxNum = team.getMaxNum();
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId",teamId);
        long hasJoinTeamCount = userTeamService.count(userTeamQueryWrapper);
        if(hasJoinTeamCount >= maxNum){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"队伍已满");
        }
        if(team.getExpireTime().before(new Date())){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"队伍已过期，无法加入");
        }
        //不能加入自己创建的队伍，不能加入已经加入的队伍
        if(Objects.equals(team.getUserId(), userId)){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"不能加入自己创建的队伍");
        }
        QueryWrapper<UserTeam> wrapper = new QueryWrapper<>();
        wrapper.eq("userId",userId);
        wrapper.eq("teamId",teamId);
        long res = userTeamService.count(wrapper);
        if(res > 0){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"不能加入已经加入的队伍");
        }
        //如果队伍状态为加密，则密码必须匹配
        String password = teamJoinRequest.getPassword();
        if(TeamStatus.SECRET.getCode() == team.getStatus()){
            if(StringUtils.isAnyBlank(password) || !team.getPassword().equals(password)){
                throw new BusinessException(ResponseCode.PARAMS_ERROR,"密码错误");
            }
        }
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userId);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());
        boolean save = userTeamService.save(userTeam);
        if(!save){
            throw new BusinessException(ResponseCode.SERVER_ERROR,"加入队伍失败，服务内部出错");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean quitTeam(TeamQuitRequest teamQuitRequest, LoginUserVO currentUser) {
        //校验参数
        if(teamQuitRequest == null){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"参数为空");
        }
        Long teamId = teamQuitRequest.getId();
        Long userId = currentUser.getId();
        //校验队伍是否存在
        Team team = this.getTeamById(teamId);
        if(team == null){
            throw new BusinessException(ResponseCode.NOT_FOUND,"队伍不存在");
        }

        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("userId",userId);
        userTeamQueryWrapper.eq("teamId",teamId);
        //校验用户是否已经加入队伍
        long count = userTeamService.count(userTeamQueryWrapper);
        if(count < 1){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"未加入该队伍");
        }
        //统计当前队伍的人数
        QueryWrapper<UserTeam> wrapper = new QueryWrapper<>();
        wrapper.eq("teamId",teamId);
        long TeamUserCount = userTeamService.count(wrapper);
        //如果只剩一个人，直接解散队伍
        if(TeamUserCount <= 1){
            //解散队伍
            boolean b = this.removeById(teamId);
            //删除用户与队伍关联表中数据
            if(!b){
                throw new BusinessException(ResponseCode.SERVER_ERROR,"删除队伍失败，服务内部出错");
            }
        }
        //队伍中还有其他人
        else{
            //如果退出队伍的用户是队长，则队长转给第二早加入的队员
            if(Objects.equals(team.getUserId(), userId)){
                QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("teamId",teamId);
                queryWrapper.last("order by id asc limit 2");
                List<UserTeam> userTeamList = userTeamService.list(queryWrapper);
                if(CollectionUtils.isEmpty(userTeamList) || userTeamList.size() <= 1){
                    throw new BusinessException(ResponseCode.SERVER_ERROR,"服务内部出错");
                }
                //新的队长
                UserTeam nextLeaderUser = userTeamList.get(1);
                Long leaderUserUserId = nextLeaderUser.getUserId();
                //更新数据库中的队长ID信息
                Team newTeam = new Team();
                newTeam.setId(teamId);
                newTeam.setUserId(leaderUserUserId);
                boolean update = this.updateById(newTeam);
                if(!update){
                    throw new BusinessException(ResponseCode.SERVER_ERROR,"服务内部出错");
                }
            }

        }
        //删除用户与队伍关联表中数据
        return userTeamService.remove(userTeamQueryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteTeam(TeamDeleteRequest teamDeleteRequest, LoginUserVO currentUser) {
        //校验参数
        if(teamDeleteRequest == null){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"参数为空");
        }
        Long teamId = teamDeleteRequest.getId();
        Long userId = currentUser.getId();
        //校验队伍是否存在
        Team team = this.getTeamById(teamId);
        if(team == null){
            throw new BusinessException(ResponseCode.NOT_FOUND,"队伍不存在");
        }
        //判断该用户是不是队长
        QueryWrapper<Team> wrapper = new QueryWrapper<>();
        wrapper.eq("userId", userId);
        long count = this.count(wrapper);
        if(count < 1){
            throw new BusinessException(ResponseCode.NO_AUTH,"无操作权限");
        }
        //移除所有用户与队伍的关联
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId",teamId);
        boolean remove = userTeamService.remove(userTeamQueryWrapper);
        if(!remove){
            throw new BusinessException(ResponseCode.SERVER_ERROR,"服务内部出错");
        }
        return this.removeById(teamId);
    }

    @Override
    public TeamVO getTeamById(TeamQueryRequest teamQueryRequest, LoginUserVO currentUser) {
        //校验参数是否为空
        if(teamQueryRequest == null){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"参数为空");
        }
        Long teamId = teamQueryRequest.getId();
        Team team = new Team();
        if(teamId != null){
            team = this.getTeamById(teamId);
        }
        TeamVO teamVo = getTeamVo(team);
        return teamVo;
    }

    @Override
    public List<TeamVO> listUserCreateTeam(LoginUserVO currentUser) {
        Long userId = currentUser.getId();
        if(userId == null){
            throw new BusinessException(ResponseCode.NOT_LOGIN,"未登录");
        }
        QueryWrapper<Team> wrapper = new QueryWrapper<>();
        wrapper.eq("userId",userId);
        List<Team> teamList = this.list(wrapper);
        if(teamList.isEmpty()){
            throw new BusinessException(ResponseCode.NOT_FOUND,"未创建任何队伍");
        }
        return this.getTeamVoList(teamList);
    }

    @Override
    public List<TeamVO> listUserJoinTeam(LoginUserVO currentUser) {
        Long userId = currentUser.getId();
        if(userId == null){
            throw new BusinessException(ResponseCode.NOT_LOGIN,"未登录");
        }
        //查询该用户加入和创建的队伍列表
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("userId",userId);
        List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
        List<Long> userTeamIdList = new ArrayList<>();
        if(!userTeamList.isEmpty()){
            userTeamList.forEach(userTeam -> userTeamIdList.add(userTeam.getTeamId()));
        }
        //查询该用户创建的队伍列表
        QueryWrapper<Team> teamQueryWrapper = new QueryWrapper<>();
        teamQueryWrapper.eq("userId",userId);
        List<Team> teamList = this.list(teamQueryWrapper);
        List<Long> TeamIdList = new ArrayList<>();
        if(!teamList.isEmpty()){
            teamList.forEach(team -> TeamIdList.add(team.getId()));
        }
        //从用户加入和创建的队伍列表中过滤掉创建的队伍
        List<Long> JoinTeamListId = new ArrayList<>();
        List<TeamVO> JoinTeamVoList = new ArrayList<>();
        if(!userTeamIdList.isEmpty()){
            JoinTeamListId = userTeamIdList.stream().filter(userTeamId -> !TeamIdList.contains(userTeamId)).collect(Collectors.toList());
            if(!JoinTeamListId.isEmpty()){
                for(Long JoinTeamId : JoinTeamListId){
                    Team team = this.getById(JoinTeamId);
                    JoinTeamVoList.add(this.getTeamVo(team));
                }
                return JoinTeamVoList;
            }
        }
        else{
            for(Long TeamId : userTeamIdList){
                Team team = this.getById(TeamId);
                JoinTeamVoList.add(this.getTeamVo(team));
            }
        }
        return JoinTeamVoList;
    }

    @Override
    public List<TeamVO> listUserNotJoinTeam(LoginUserVO currentUser) {
        Long userId = currentUser.getId();
        if(userId == null){
            throw new BusinessException(ResponseCode.NOT_LOGIN,"未登录");
        }
        //查询所有队伍ID
        List<Team> teamList = this.list();
        List<Long> teamIdList = teamList.stream().map(Team::getId).collect(Collectors.toList());
        //查询该用户加入和创建的队伍ID列表
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("userId",userId);
        List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
        List<Long> userTeamIdList = new ArrayList<>();
        if(!userTeamList.isEmpty()){
            userTeamList.forEach(userTeam -> userTeamIdList.add(userTeam.getTeamId()));
        }
        //从所有队伍列表中过滤掉该用户创建和加入的队伍
        List<Long> NotJoinTeamListId = new ArrayList<>();
        List<TeamVO> JoinTeamVoList = new ArrayList<>();
        NotJoinTeamListId = teamIdList.stream().filter(teamId -> !userTeamIdList.contains(teamId)).collect(Collectors.toList());
        if(!NotJoinTeamListId.isEmpty()){
            for(Long JoinTeamId : NotJoinTeamListId){
                Team team = this.getById(JoinTeamId);
                JoinTeamVoList.add(this.getTeamVo(team));
            }
            return JoinTeamVoList;
        }
        return Collections.emptyList();
    }

    /**
     * 根据ID查询队伍是否存在
     */
    private Team getTeamById(Long teamId){
        QueryWrapper<Team> wrapper = new QueryWrapper<>();
        wrapper.eq("id",teamId);
        return this.getById(teamId);
    }

    /**
     * 构建队伍脱敏数据
     */
    private TeamVO getTeamVo(Team team){
        TeamVO teamVO = new TeamVO();
        BeanUtils.copyProperties(team,teamVO);
        //添加脱敏用户(队长)信息
        Long LeaderId = team.getUserId();
        QueryWrapper<User> LeaderuserQueryWrapper = new QueryWrapper<>();
        LeaderuserQueryWrapper.eq("id",LeaderId);
        User Leader = userService.getOne(LeaderuserQueryWrapper);
        UserVO LeaderVO = userService.getUserVO(Leader);
        teamVO.setLeaderVO(LeaderVO);
        //添加脱敏用户(队员)信息
        Long teamId = team.getId();
        List<UserVO> teamUserVOS = new ArrayList<>();
        //根据队伍id查询用户队伍关系表，得到用户ID列表
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId", teamId);
        List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
        for(UserTeam userTeam : userTeamList){
            //根据用户ID查询用户表，得到用户信息
            Long teamUserId = userTeam.getUserId();
            //去除队长信息
            if(Objects.equals(teamUserId, LeaderId)){
                continue;
            }
            User user = userService.getById(teamUserId);
            UserVO userVO = userService.getUserVO(user);
            teamUserVOS.add(userVO);
        }
        teamVO.setTeamUserVOS(teamUserVOS);
        return teamVO;
    }

    /**
     * 构建脱敏列表数据
     */
    private List<TeamVO> getTeamVoList(List<Team> teamList){
        ArrayList<TeamVO> teamVOList = new ArrayList<>();
        for(Team team : teamList){
            teamVOList.add(this.getTeamVo(team));
        }
        return teamVOList;
    }
}